unit QuickList_TimeEventItem;

interface

uses               
  QuickSortList,
  define_datetime,
  define_timemachine;

type
  PTimeEventItemListItem = ^TTimeEventItemListItem;
  TTimeEventItemListItem = record
    DayTime         : TDateTimeM0;
    TimeEventItem   : PTimeEventItem;
  end;
                        
  TTimeEventItemList = class(TALBaseQuickSortList)
  public
    function  GetItem(AIndex: Integer): TDateTimeM0;
    procedure SetItem(AIndex: Integer; const ADayTime: TDateTimeM0);
    function  GetTimeEventItem(AIndex: Integer): PTimeEventItem;
    procedure PutTimeEventItem(AIndex: Integer; ATimeEventItem: PTimeEventItem);
  public
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
    procedure InsertItem(AIndex: Integer; const ADayTime: TDateTimeM0; ATimeEventItem: PTimeEventItem);
    function  CompareItems(const Index1, Index2: Integer): Integer; override;
  public
    function  IndexOf(ADayTime: TDateTimeM0): Integer;
    function  IndexOfTimeEventItem(ATimeEventItem: PTimeEventItem): Integer;
    Function  AddTimeEventItem(const ADayTime: TDateTimeM0; ATimeEventItem: PTimeEventItem): Integer;
    function  Find(ADayTime: TDateTimeM0; var AIndex: Integer): Boolean;
    procedure InsertObject(AIndex: Integer; const ADayTime: TDateTimeM0; ATimeEventItem: PTimeEventItem);
    //property  Items[Index: Integer]: Integer read GetItem write SetItem; default;
    property  DayTime[Index: Integer]: TDateTimeM0 read GetItem write SetItem; default;
    property  TimeEventItem[Index: Integer]: PTimeEventItem read GetTimeEventItem write PutTimeEventItem;
  end;
  
implementation

function TTimeEventItemList.AddTimeEventItem(const ADayTime: TDateTimeM0; ATimeEventItem: PTimeEventItem): Integer;
begin
  if not Sorted then
  begin
    Result := FCount
  end else if Find(ADayTime, Result) then
  begin
    case Duplicates of
      lstDupIgnore: Exit;
      lstDupError: Error(@SALDuplicateItem, 0);
    end;
  end;
  InsertItem(Result, ADayTime, ATimeEventItem);
end;

{*****************************************************************************************}
procedure TTimeEventItemList.InsertItem(AIndex: Integer; const ADayTime: TDateTimeM0; ATimeEventItem: PTimeEventItem);
var
  tmpListItem: PTimeEventItemListItem;
begin
  New(tmpListItem);
  tmpListItem^.TimeEventItem := ATimeEventItem;
  try
    inherited InsertItem(Aindex, tmpListItem);
  except
    Dispose(tmpListItem);
    raise;
  end;
end;

{***************************************************************************}
function TTimeEventItemList.CompareItems(const Index1, Index2: integer): Integer;
begin
  result := PTimeEventItemListItem(Get(Index1))^.DayTime.Date - PTimeEventItemListItem(Get(Index2))^.DayTime.Date;
end;

{***********************************************************************}
function TTimeEventItemList.Find(ADayTime: TDateTimeM0; var AIndex: Integer): Boolean;
var
  L: Integer;
  H: Integer;
  I: Integer;
  C: double;
begin
  Result := False;
  L := 0;
  H := FCount - 1;
  while L <= H do
  begin
    I := (L + H) shr 1;
    C := GetItem(I).Date - ADayTime.Date;
    if C < 0 then
    begin
      L := I + 1
    end else
    begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        if Duplicates <> lstDupAccept then
          L := I;
      end;
    end;
  end;
  AIndex := L;
end;

{*******************************************************}
function TTimeEventItemList.GetItem(AIndex: Integer): TDateTimeM0;
begin
  Result := PTimeEventItemListItem(Get(Aindex))^.DayTime
end;

{******************************************************}
function TTimeEventItemList.IndexOf(ADayTime: TDateTimeM0): Integer;
begin
  if not Sorted then
  Begin
    Result := 0;
    while (Result < FCount) and (GetItem(result).Date <> ADayTime.Date) do
    begin
      Inc(Result);
    end;
    if Result = FCount then
    begin
      Result := -1;
    end;
  end else if not Find(ADayTime, Result) then
    Result := -1;
end;
{*******************************************************************************************}
procedure TTimeEventItemList.InsertObject(AIndex: Integer; const ADayTime: TDateTimeM0; ATimeEventItem: PTimeEventItem);
var
  tmpListItem: PTimeEventItemListItem;
begin
  New(tmpListItem);
  tmpListItem^.DayTime.Date := ADayTime.Date;
  tmpListItem^.TimeEventItem := ATimeEventItem;
  try
    inherited insert(Aindex, tmpListItem);
  except
    Dispose(tmpListItem);
    raise;
  end;
end;

{***********************************************************************}
procedure TTimeEventItemList.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if Action = lstDeleted then
    dispose(ptr);
  inherited Notify(Ptr, Action);
end;

{********************************************************************}
procedure TTimeEventItemList.SetItem(AIndex: Integer; const ADayTime: TDateTimeM0);
Var
  tmpListItem: PTimeEventItemListItem;
begin
  New(tmpListItem);
  tmpListItem^.DayTime.Date := ADayTime.Date;
  tmpListItem^.TimeEventItem := nil;
  Try
    Put(AIndex, tmpListItem);
  except
    Dispose(tmpListItem);
    raise;
  end;
end;

{*********************************************************}
function TTimeEventItemList.GetTimeEventItem(AIndex: Integer): PTimeEventItem;
begin
  if (AIndex < 0) or (AIndex >= FCount) then
    Error(@SALListIndexError, AIndex);
  Result :=  PTimeEventItemListItem(Get(Aindex))^.TimeEventItem;
end;

{***************************************************************}
function TTimeEventItemList.IndexOfTimeEventItem(ATimeEventItem: PTimeEventItem): Integer;
begin
  for Result := 0 to Count - 1 do
  begin
    if GetTimeEventItem(Result) = ATimeEventItem then
    begin
      Exit;
    end;
  end;
  Result := -1;
end;

{*******************************************************************}
procedure TTimeEventItemList.PutTimeEventItem(AIndex: Integer; ATimeEventItem: PTimeEventItem);
begin
  if (AIndex < 0) or (AIndex >= FCount) then
  begin
    Error(@SALListIndexError, AIndex);
  end;
  PTimeEventItemListItem(Get(Aindex))^.TimeEventItem := ATimeEventItem;
end;

end.
